package com.sky.service.impl;

import com.google.common.collect.Maps;
import com.sky.config.MinioConfig;
import com.sky.constant.Constants;
import com.sky.entity.SysFile;
import com.sky.service.ISysFileService;
import com.sky.utils.FileUploadUtils;
import com.sky.utils.FileUtils;
import com.sky.utils.ServletUtils;
import io.minio.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Primary;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;
import java.util.Objects;

/**
 * Minio 文件存储
 *
 * @author tzl
 */
@Primary
@Service
public class MinioSysFileServiceImpl implements ISysFileService
{
    @Autowired
    private MinioConfig minioConfig;

    @Autowired
    @Qualifier("getMinioClient")
    private MinioClient client;

    /**
     * 本地文件上传接口
     *
     * @param file 上传的文件
     * @return 访问地址
     * @throws Exception
     */
    @Override
    public SysFile uploadFile(MultipartFile file) throws Exception {
        String fileName = FileUploadUtils.extractFilename(file);
        PutObjectArgs args = PutObjectArgs.builder()
                .bucket(minioConfig.getBucketName())
                .object(fileName)
                .stream(file.getInputStream(), file.getSize(), -1)
                .contentType(file.getContentType())
                .build();
        client.putObject(args);
        String url = minioConfig.getUrl()
                + "/"
                + minioConfig.getBucketName()
                + "/"
                + fileName;
        SysFile sysFile = new SysFile();
        sysFile.setUrl(url);
        sysFile.setName(FileUtils.getName(url));
        sysFile.setSize(file.getSize());
        //相对路径 = minlo桶名称 + 文件存储路径
        sysFile.setRelativeUrl("/" + minioConfig.getBucketName() + "/" + fileName);
        return sysFile;
    }

    @Override
    public void deleteFile(String fileName) throws Exception {
        client.removeObject(
                RemoveObjectArgs.builder().bucket(minioConfig.getBucketName()).object(fileName).build());
    }

    /**
     * 根据 URL 地址获取文件名。
     *
     * @param url 文件的 URL 地址
     * @return 去除前缀文件名
     */
    @Nullable
    public String getName(@Nullable String url) {
        if (url != null && url.startsWith(minioConfig.getUrl())) {
            return url.substring(minioConfig.getUrl().length());
        }
        return null;
    }

    /**
     * 获取文件byte[]
     *
     * @param objectName 存储桶里的对象名称
     * @return 结果
     */
    @Override
    public byte[] getObjectByte(String objectName) throws Exception {
        // 获取桶
        HttpServletRequest request = Objects.requireNonNull(ServletUtils.getRequest(), "request is null");
        String bucketName = minioConfig.getBucketName();

        // 去除前缀:/桶名称/
        objectName = objectName.replaceAll(Constants.SLASH + bucketName + Constants.SLASH, Constants.EMPTY);
        GetObjectArgs objectArgs = GetObjectArgs.builder()
                .bucket(bucketName)
                .object(objectName)
                .build();
        GetObjectResponse object = client.getObject(objectArgs);
        return object.readAllBytes();
    }

    /**
     * 获取文件byte[]
     */
    @Override
    public Map<String, byte[]> getObjectByteMap(Map<String, String> keyToPath) throws Exception {
        Map<String, byte[]> keyToStream = Maps.newHashMapWithExpectedSize(keyToPath.size());
        for (Map.Entry<String, String> keyPathEntry : keyToPath.entrySet()) {
            byte[] objectByte = getObjectByte(keyPathEntry.getValue());
            keyToStream.put(keyPathEntry.getKey(), objectByte);
        }
        return keyToStream;
    }
}
